import shutil

import pandas as pd
from pandas.core.interchange.dataframe_protocol import DataFrame
from tools import BASE_5G生态应用技术

pd.set_option('display.unicode.east_asian_width', True)


def _copy_docx(source_path, destination_path):
    """
    从作业模板文件复制出各个同学的作业 docx 文件
    """
    try:
        shutil.copy2(source_path, destination_path)
        print(f"文件复制成功: {source_path} -> {destination_path}")
        return True
    except FileNotFoundError:
        print(f"错误: 源文件不存在 - {source_path}")
    except PermissionError:
        print(f"错误: 没有权限复制文件 - {source_path}")
    except Exception as e:
        print(f"复制文件出错: {str(e)}")
    return False


def copy_docx(作业='作业1'):
    xlsx_from_path = f"{BASE_5G生态应用技术}/上机资料/{作业}/成绩附件-{作业}.xlsx"
    df = pd.read_excel(xlsx_from_path, usecols=['学号', '姓名', '最终成绩', '提交次数'],
                       dtype={'学号': int, '姓名': str, '最终成绩': int, '提交次数': int})
    for idx, row in df.iterrows():
        学号 = row.iloc[0]
        姓名 = row.iloc[1]
        成绩 = row.iloc[2]
        提交次数 = row.iloc[3]

        from_file_path = f"{BASE_5G生态应用技术}/{作业}/{作业}-模板.docx"
        to_file_path = f"{BASE_5G生态应用技术}/{作业}/{作业}-{学号}-{姓名}.docx"
        if 提交次数 > 0:
            _copy_docx(from_file_path, to_file_path)


def read_specific_columns(file_path, columns, dtype, header_row, converters):
    """
    从Excel文件中读取指定列的数据

    参数:
        file_path (str): Excel文件路径
        columns (list): 要读取的列索引列表（从0开始计数）
        header_row (int): 标题行索引（默认为0，即第一行）

    返回:
        pd.DataFrame: 包含指定列数据的DataFrame
    """

    try:
        # 读取Excel文件中的指定列
        df = pd.read_excel(file_path,
                           usecols=columns,
                           dtype=dtype,
                           header=header_row,
                           converters=converters)

        # 打印读取的信息
        print(f"✅ 成功读取文件: {file_path}")
        print(f"读取的列: {df.columns.tolist()}")
        print(f"总行数: {len(df)}")

        return df

    except Exception as e:
        print(f"❌ 读取失败: {str(e)}")
        raise


def get_作业_成绩(作业='作业1') -> DataFrame:
    file_path = f"{BASE_PATH_5G生态应用技术}/{作业}/成绩附件-{作业}.xlsx"

    # 为特定列指定默认值
    converters = {
        '学号': lambda x: int(x) if str(x).strip() not in ["N/A", ""] else 0,
        '最终成绩': lambda x: float(x) if str(x).strip() not in ["N/A", ""] else 0
    }

    # 注意：索引从0开始，所以第1列索引0
    selected_df = read_specific_columns(
        file_path=file_path,
        columns=['学号', '最终成绩'],
        dtype={'学号': int, '最终成绩': int},
        header_row=0,
        converters=converters
    )

    # 显示读取的数据
    print("\n读取的数据:")
    print(selected_df)

    df_学生信息 = get_学生_信息()
    # 合并数据
    merged_data = merge_student_homework(
        df_stu_info=df_学生信息,
        df_homework=selected_df,
        output_path=f"{BASE_PATH_5G生态应用技术}/{作业}/成绩附件-{作业}-新.xlsx",
    )

    print("\n合并后的数据:")
    print(merged_data)

    return selected_df


def get_学生_信息() -> DataFrame:
    file_path = f"{BASE_5G生态应用技术}/上机资料/学生名单.xlsx"

    # 注意：索引从0开始，所以第1列索引0
    selected_df = read_specific_columns(
        file_path=file_path,
        columns=['学号', '姓名'],
        dtype={'学号': int, '姓名': str},
        header_row=0,
    )

    # 显示读取的数据
    print("\n读取的数据:")
    print(selected_df)
    return selected_df


def merge_student_homework(df_stu_info, df_homework, output_path=None,
                           id_col='学号', name_col='姓名', score_col='最终成绩'):
    """
    合并学生信息与作业成绩数据

    参数:
        df_stu_info (pd.DataFrame): 学生信息DataFrame（完整学生列表）
        df_homework (pd.DataFrame): 学生作业成绩DataFrame
        output_path (str): 输出Excel文件路径（可选）
        id_col (str): 学号列名（默认为'学号'）
        name_col (str): 姓名列名（默认为'姓名'）
        score_col (str): 成绩列名（默认为'最终成绩'）

    返回:
        pd.DataFrame: 合并后的DataFrame，包含学号、姓名和作业1成绩
    """
    try:
        # 验证输入DataFrame
        if id_col not in df_stu_info.columns:
            raise ValueError(f"学生信息DataFrame中缺少学号列: {id_col}")
        if name_col not in df_stu_info.columns:
            raise ValueError(f"学生信息DataFrame中缺少姓名列: {name_col}")
        if id_col not in df_homework.columns:
            raise ValueError(f"作业成绩DataFrame中缺少学号列: {id_col}")
        if score_col not in df_homework.columns:
            raise ValueError(f"作业成绩DataFrame中缺少成绩列: {score_col}")

        # 1. 从作业成绩中只保留需要的列（学号和成绩）
        # 重命名成绩列为"作业1"
        df_homework_selected = df_homework[[id_col, score_col]].rename(
            columns={score_col: '作业1'}
        )

        # 2. 合并学生信息和作业成绩（左连接）
        merged_df = pd.merge(
            df_stu_info[[id_col, name_col]],  # 只保留学号和姓名
            df_homework_selected,
            on=id_col,
            how='left'  # 左连接保留所有学生
        )

        # 3. 处理缺失值（将缺失成绩填充为0）
        merged_df['作业1'] = merged_df['作业1'].fillna(0)

        # 4. 如果需要，保存到Excel
        if output_path:
            merged_df.to_excel(output_path, index=False)
            print(f"✅ 数据合并完成! 文件已保存至: {output_path}")

        # 5. 打印统计信息
        total_students = len(merged_df)
        homework_present = merged_df['作业1'].ne(0).sum()
        print(f"总学生数: {total_students}")
        print(f"有作业成绩的学生数: {homework_present} ({homework_present / total_students:.1%})")
        print(f"缺失作业成绩的学生数: {total_students - homework_present}")

        return merged_df

    except Exception as e:
        print(f"❌ 合并失败: {str(e)}")
        raise


import pandas as pd


def merge_student_homeworks(df_stu_info, homework_dfs, output_path=None,
                            id_col='学号', name_col='姓名',
                            fill_value=0, validate_names=True):
    """
    合并多个学生作业成绩DataFrame

    参数:
        df_stu_info (pd.DataFrame): 学生信息DataFrame（包含完整学生名单）
        homework_dfs (list): 作业成绩DataFrame列表，每个包含学号、姓名和作业成绩列
        output_path (str): 输出Excel文件路径（可选）
        id_col (str): 学号列名（默认为'学号'）
        name_col (str): 姓名列名（默认为'姓名'）
        fill_value: 缺失值填充值（默认为0）
        validate_names: 是否验证姓名一致性

    返回:
        pd.DataFrame: 合并后的DataFrame，包含学号、姓名和所有作业成绩
    """
    try:
        # 验证输入DataFrame
        if id_col not in df_stu_info.columns:
            raise ValueError(f"学生信息DataFrame中缺少学号列: {id_col}")
        if name_col not in df_stu_info.columns:
            raise ValueError(f"学生信息DataFrame中缺少姓名列: {name_col}")

        # 1. 创建基础合并DataFrame（只包含学号和姓名）
        merged_df = df_stu_info[[id_col, name_col]].copy()

        # 2. 遍历所有作业DataFrame
        for i, df_homework in enumerate(homework_dfs, 1):
            # 验证当前作业DataFrame
            if id_col not in df_homework.columns:
                raise ValueError(f"作业{i}DataFrame中缺少学号列: {id_col}")

            # 获取作业成绩列名（假设是除了学号和姓名外的第一列）
            possible_score_cols = [col for col in df_homework.columns
                                   if col not in [id_col, name_col]]

            if not possible_score_cols:
                raise ValueError(f"作业{i}DataFrame中没有找到成绩列")

            # 使用第一个可能的成绩列
            score_col = possible_score_cols[0]
            new_col_name = f"作业{i}"

            # 选择并重命名成绩列
            df_homework_selected = df_homework[[id_col, score_col]].rename(
                columns={score_col: new_col_name}
            )

            # 合并当前作业成绩
            merged_df = pd.merge(
                merged_df,
                df_homework_selected,
                on=id_col,
                how='left'
            )

            # 填充缺失成绩
            merged_df[new_col_name] = merged_df[new_col_name].fillna(fill_value)

            # 姓名一致性检查（可选）
            if validate_names and name_col in df_homework.columns:
                # 临时合并以获取作业中的姓名
                temp_df = pd.merge(
                    merged_df[[id_col, name_col]],
                    df_homework[[id_col, name_col]].rename(columns={name_col: f'作业{i}_姓名'}),
                    on=id_col,
                    how='left'
                )

                # 检查姓名是否匹配
                name_mismatch = temp_df[
                    (temp_df[name_col] != temp_df[f'作业{i}_姓名']) &
                    (~temp_df[f'作业{i}_姓名'].isna())
                    ]

                if not name_mismatch.empty:
                    print(f"⚠️ 警告(作业{i}): 发现 {len(name_mismatch)} 条姓名不一致的记录")
                    print(name_mismatch)

            print(f"✅ 已合并作业{i}数据")

        # 3. 如果需要，保存到Excel
        if output_path:
            merged_df.to_excel(output_path, index=False)
            print(f"\n✅ 所有作业合并完成! 文件已保存至: {output_path}")

        return merged_df

    except Exception as e:
        print(f"❌ 合并失败: {str(e)}")
        raise


# 使用示例
if __name__ == "__main__":
    df_学生_信息 = get_学生_信息()
    df_作业1 = get_作业_成绩('作业1')
    df_作业2 = get_作业_成绩('作业2')
    df_作业3 = get_作业_成绩('作业3')
    df_作业4 = get_作业_成绩('作业4')
    df_作业5 = get_作业_成绩('作业5')

    # 所有作业列表
    all_homeworks = [df_作业1, df_作业2, df_作业3, df_作业4, df_作业5]

    print("学生信息:")
    print(df_学生_信息)

    # 合并所有作业
    merged_data = merge_student_homeworks(
        df_stu_info=df_学生_信息,
        homework_dfs=all_homeworks,
        output_path=f"{BASE_PATH_5G生态应用技术}/作业成绩_汇总.xlsx",
        fill_value=-1,  # 用-1表示缺失成绩
        validate_names=True
    )

    print("\n合并后的数据:")
    print(merged_data)
